/**
 * Notes: 设备服务层
 * Date: 2025-01-27
 */

const BaseService = require('./base_service.js');
const DeviceModel = require('../model/device_model.js');
const timeUtil = require('../../framework/utils/time_util.js');
const util = require('../../framework/utils/util.js');
const AppError = require('../../framework/core/app_error.js');
const appCode = require('../../framework/core/app_code.js');
const mqtt = require('mqtt'); // MQTT库
// 全局设备缓存，跨云函数请求共享，避免 deviceCache 未定义
const deviceCache = global.DEVICE_CACHE || (global.DEVICE_CACHE = new Map());
const config = require('../../config/config.js');

class DeviceService extends BaseService {

	constructor() {
		super();
		// MQTT配置
		// 初始化静态 MQTT 配置（仅一次）
		if (!DeviceService._mqttStaticConfig) {
			DeviceService._mqttStaticConfig = {
				protocol: 'mqtt',
				host: 'mqtt.geek-smart.cn',
				port: 1883,
				username: 'DZcZhkJkcRQz',
				password: 'hYvkOOCvRuChYUYHKZ',
				clientId: 'vIGuEvWZmWFk'
			};
			try { Object.freeze(DeviceService._mqttStaticConfig); } catch (e) { /* ignore */ }
		}
		// 只读映射：this.mqttConfig 始终返回静态配置
		Object.defineProperty(this, 'mqttConfig', {
			configurable: false,
			enumerable: true,
			get() { return DeviceService._mqttStaticConfig; }
		});
		this.mqttClient = null;
		// MQTT连接重试控制
		this.mqttRetryCount = 0;
		this.mqttMaxRetries = 3; // 若连接失败达到3次，不再自动重试
		this.mqttReconnectDelayMs = 3000; // 重试间隔
		this.mqttConnecting = false; // 防止并发连接
		// 永久性错误与失败去重控制
		this.mqttPermanentFail = false;
		this.mqttLastFailureTs = 0;
		this.mqttFailureCooldownMs = 1000;

		// === 将MQTT状态改为模块级共享，避免多处 new DeviceService 导致重试计数被重置 ===
		if (!DeviceService._mqttShared) {
			DeviceService._mqttShared = {
				client: null,
				retryCount: 0,
				maxRetries: this.mqttMaxRetries,
				reconnectDelayMs: this.mqttReconnectDelayMs,
				connecting: false,
				permanentFail: false,
				lastFailureTs: 0,
				failureCooldownMs: this.mqttFailureCooldownMs,
				retryScheduled: false,
				lastConfig: null
			};
		}
		const mapProp = (sharedKey, propName) => {
			Object.defineProperty(this, propName, {
				get() { return DeviceService._mqttShared[sharedKey]; },
				set(v) { DeviceService._mqttShared[sharedKey] = v; }
			});
		};
		mapProp('client', 'mqttClient');
		mapProp('retryCount', 'mqttRetryCount');
		mapProp('maxRetries', 'mqttMaxRetries');
		mapProp('reconnectDelayMs', 'mqttReconnectDelayMs');
		mapProp('connecting', 'mqttConnecting');
		mapProp('permanentFail', 'mqttPermanentFail');
		mapProp('lastFailureTs', 'mqttLastFailureTs');
		mapProp('failureCooldownMs', 'mqttFailureCooldownMs');
		mapProp('retryScheduled', 'mqttRetryScheduled');
		mapProp('lastConfig', 'mqttLastConfig');
	}

	/**
	 * 初始化MQTT连接（带最多3次重试，过限后不再自动重连）
	 */
	async initMqttConnection() {
		// 若存在永久性错误，停止尝试并提示
		if (this.mqttPermanentFail) {
			console.warn('MQTT存在永久性连接错误，已停止连接尝试');
			return;
		}
		// 已连接则检查凭据是否一致，不一致则重建连接
		if (this.mqttClient && this.mqttClient.connected) {
			const last = this.mqttLastConfig || {};
			const cfg = this.mqttConfig || {};
			const same = last.host === cfg.host && last.port === cfg.port && last.username === cfg.username && last.clientId === cfg.clientId && last.password === cfg.password;
			if (same) {
				console.log('MQTT已连接，凭据一致，跳过重复连接');
				return;
			} else {
				console.log('检测到MQTT凭据变更，重建连接');
				try { this.mqttClient.end(true); } catch (e) { console.warn('关闭旧MQTT客户端异常:', e); }
				this.mqttClient = null;
				this.mqttConnecting = false;
			}
		}
		// 若正在连接，避免并发
		if (this.mqttConnecting) {
			console.log('MQTT正在连接中，跳过并发调用');
			return;
		}
		// 超过最大重试次数则停止尝试
		if (this.mqttRetryCount >= this.mqttMaxRetries) {
			console.warn(`MQTT连接失败已达${this.mqttRetryCount}次，停止自动重连`);
			return;
		}

		try {
			this.mqttConnecting = true;
			this.mqttRetryScheduled = false; // 重置延迟重试调度标记
			console.log(`开始建立MQTT连接（第${this.mqttRetryCount + 1}次尝试）...`);
			// 关闭自动重连，由我们自行控制重试次数
			// const protocol = this.mqttConfig.protocol ? this.mqttConfig.protocol : ((this.mqttConfig.port === 8883 || this.mqttConfig.tls === true) ? 'mqtts' : 'mqtt');
			// 构造连接选项，仅使用 this.mqttConfig 中的字段，不做派生
			const options = {
				host: this.mqttConfig.host,
				port: this.mqttConfig.port,
				username: this.mqttConfig.username,
				password: this.mqttConfig.password,
				clientId: this.mqttConfig.clientId,
				reconnectPeriod: 0,
				connectTimeout: 10000,
				clean: true,
				keepalive: 60,
				protocolVersion: 4
			};
			if (this.mqttConfig.protocol) {
				options.protocol = this.mqttConfig.protocol;
			}
			const maskedOptions = {
				host: options.host,
				port: options.port,
				protocol: options.protocol,
				username: options.username ? `${String(options.username).slice(0,2)}***` : undefined,
				clientId: options.clientId ? `${String(options.clientId).slice(0,3)}***` : undefined
			};
			console.log('MQTT连接配置(已脱敏)', maskedOptions);
			this.mqttClient = mqtt.connect(options);

			this.mqttClient.on('connect', () => {
				console.log('MQTT连接成功');
				this.mqttRetryCount = 0;
				this.mqttConnecting = false;
				this.mqttRetryScheduled = false;
				// 记录当前成功连接所使用的凭据，便于后续判断是否需要切换
				this.mqttLastConfig = {
					host: this.mqttConfig.host,
					port: this.mqttConfig.port,
					username: this.mqttConfig.username,
					password: this.mqttConfig.password,
					clientId: this.mqttConfig.clientId
				};
			});

            const handleFailure = (event, err) => {
                // 失败去重：error/close/disconnect 可能同时触发，这里做冷却避免重复累计
                const now = Date.now();
                if (this.mqttLastFailureTs && now - this.mqttLastFailureTs < this.mqttFailureCooldownMs) {
                    return;
                }
                this.mqttLastFailureTs = now;
                
                if (err) console.error(`MQTT连接${event}:`, err);
                else console.error(`MQTT连接${event}`);
                
                // 如果是服务端明确拒绝（标识或认证失败），判定为永久性错误，停止重试
                const isPermanentAuthOrIdError = err && (
                    (err.message && (err.message.includes('Identifier rejected') || err.message.includes('Bad username or password') || err.message.includes('Not authorized')))
                    || (typeof err.reasonCode === 'number' && [2, 4, 5].includes(err.reasonCode))
                );
                if (isPermanentAuthOrIdError) {
                    console.error('检测到服务端认证/标识拒绝（Identifier rejected/Bad username or password/Not authorized），已停止自动重连');
                    this.mqttPermanentFail = true;
                }
                
                // 结束当前连接
                try {
                    if (this.mqttClient) this.mqttClient.end(true);
                } catch (e) {
                    console.warn('关闭MQTT客户端时发生异常:', e);
                }
                this.mqttClient = null;
                this.mqttConnecting = false;

                // 仅在真正的连接错误阶段进行自动重试，正常的 close/disconnect 不再触发重试，避免反复抖动
                const shouldRetry = event === '错误' && !this.mqttPermanentFail;
                if (!shouldRetry) {
                    this.mqttRetryScheduled = false;
                    return;
                }
                
                this.mqttRetryCount++;
                if (this.mqttRetryCount >= this.mqttMaxRetries) {
                    console.error(`MQTT连接失败次数达到${this.mqttRetryCount}，不再自动重连`);
                    this.mqttRetryScheduled = false;
                    return;
                }
                // 延时重试（确保同一时刻最多只有一个重试调度）
                if (!this.mqttRetryScheduled) {
                    this.mqttRetryScheduled = true;
                    setTimeout(() => {
                        this.mqttRetryScheduled = false;
                        this.initMqttConnection();
                    }, this.mqttReconnectDelayMs);
                }
            };

			this.mqttClient.on('error', (error) => handleFailure('错误', error));
			this.mqttClient.on('close', () => handleFailure('已关闭'));
			this.mqttClient.on('disconnect', () => handleFailure('已断开'));

		} catch (error) {
			this.mqttConnecting = false;
			console.error('MQTT初始化失败:', error);
			this.mqttRetryCount++;
			if (this.mqttRetryCount < this.mqttMaxRetries) {
				setTimeout(() => {
					this.initMqttConnection();
				}, this.mqttReconnectDelayMs);
			} else {
				console.error(`MQTT初始化失败次数达到${this.mqttRetryCount}，不再自动重连`);
			}
		}
	}

	/**
	 * 主动停止MQTT连接（可在服务关闭或超过重试次数时调用）
	 */
	stopMqttConnection() {
		try {
			if (this.mqttClient) this.mqttClient.end(true);
		} catch (e) {
			console.warn('停止MQTT连接时发生异常:', e);
		}
		this.mqttClient = null;
		this.mqttConnecting = false;
	}

	/**
	 * 获取MQTT连接状态
	 */
	getMqttConnectionStatus() {
		return {
			connected: !!(this.mqttClient && this.mqttClient.connected),
			connecting: this.mqttConnecting,
			permanentFail: this.mqttPermanentFail,
			retryCount: this.mqttRetryCount,
			maxRetries: this.mqttMaxRetries,
			retryScheduled: this.mqttRetryScheduled
		};
	}

	/**
	 * 获取门店设备列表
	 * @param {string} storeId 门店ID
	 * @returns {Array} 设备列表
	 */
	async getDeviceList(storeId) {
		// TEST_MODE下返回模拟设备列表
		if (config.TEST_MODE && !config.TEST_CONFIG.ENABLE_REAL_DEVICE_LIST) {
			console.log('TEST_MODE: 返回模拟设备列表', { storeId });
			const mockDeviceList = [
				{
					_id: 'mock_device_1',
					name: '测试烘干机1号',
					code: 'DRY001',
					iotId: 'mock_iot_1',
					type: 'dryer',
					category: 'dryer',
					location: '1号位',
					status: 0, // 可用
					isOnline: true,
					switchStatus: 'off',
					currentTemperature: 25,
					waterLevel: 80,
					remainingTime: 0,
					appId: 'mock_app',
					deviceKey: 'mock_key',
					deviceMAC: '00:11:22:33:44:55',
					clientId: 'mock_client',
					host: 'mock.host.com',
					port: 1883,
					username: 'mock_user',
					password: 'mock_pass',
					publishTopic: '/mock/device/1/control',
					subscribeTopics: ['/mock/device/1/status'],
					storeId: storeId
				},
				{
					_id: 'mock_device_2',
					name: '测试洗衣机2号',
					code: 'WASH002',
					iotId: 'mock_iot_2',
					type: 'washer',
					category: 'washer',
					location: '2号位',
					status: 1, // 使用中
					isOnline: true,
					switchStatus: 'on',
					currentTemperature: 40,
					waterLevel: 60,
					remainingTime: 1800, // 30分钟
					appId: 'mock_app',
					deviceKey: 'mock_key',
					deviceMAC: '00:11:22:33:44:66',
					clientId: 'mock_client',
					host: 'mock.host.com',
					port: 1883,
					username: 'mock_user',
					password: 'mock_pass',
					publishTopic: '/mock/device/2/control',
					subscribeTopics: ['/mock/device/2/status'],
					storeId: storeId
				}
			];

			// 处理模拟设备数据，添加状态描述和设备信息
			for (let device of mockDeviceList) {
				if (device && device._id) deviceCache.set(device._id, device);
				device.statusDesc = DeviceModel.STATUS_DESC[device.status] || '未知';
				// 根据设备类型添加特定信息
				device = this.enrichDeviceInfo(device);
			}

			return mockDeviceList;
		}

		let where = {
			storeId: storeId,
			// 过滤掉门禁设备，门禁设备不显示在设备列表中
			type: { $ne: 'access_control' }
		};
		// 包含必要的MQTT字段，便于后续控制时无需再次查询即可解析发布主题
		let fields = '_id,name,code,iotId,type,category,location,status,isOnline,switchStatus,currentTemperature,waterLevel,remainingTime,appId,deviceKey,deviceMAC,clientId,host,port,username,password,publishTopic,subscribeTopics';
		let orderBy = { createTime: -1 };

		// 重要修复：关闭 _pid 强校验，避免旧数据未写入 _pid 导致查询为空
		let deviceList = await DeviceModel.getAll(where, fields, orderBy, 100, false);

		// 将设备信息写入全局缓存
		for (let device of deviceList) {
			if (device && device._id) deviceCache.set(device._id, device);
			device.statusDesc = DeviceModel.STATUS_DESC[device.status] || '未知';
			// 根据设备类型添加特定信息
			device = this.enrichDeviceInfo(device);
		}

		return deviceList;
	}

	/**
	 * 获取设备详情
	 * @param {string} deviceId 设备ID
	 * @returns {Object} 设备详情
	 */
	async getDeviceDetail(deviceId) {
		// 临时绕过_pid验证，因为现有设备数据可能缺少_pid字段
		let device = await DeviceModel.getOne(deviceId, '*', {}, false);
		if (!device) {
			// 如果不带_pid查询失败，尝试带_pid查询
			device = await DeviceModel.getOne(deviceId);
		}
		if (!device) {
			throw new AppError('设备不存在', appCode.DATA_NOT_EXIST);
		}

		// 写入缓存
		if (device && device._id) deviceCache.set(device._id, device);

		device.statusDesc = DeviceModel.STATUS_DESC[device.status] || '未知';
		device = this.enrichDeviceInfo(device);

		return device;
	}

	/**
	 * 丰富设备信息
	 * @param {Object} device 设备信息
	 * @returns {Object} 丰富后的设备信息
	 */
	enrichDeviceInfo(device) {
		// 根据设备类型添加图标和描述
		switch (device.type) {
			case 'bath':
				device.icon = '/assets/equipment-list/icon_bath.png';
				device.iconUsing = '/assets/equipment-list/icon_bath_use.png';
				device.typeDesc = '洗浴池';
				break;
			case 'dry':
				device.icon = '/assets/equipment-list/icon_dryer.png';
				device.iconUsing = '/assets/equipment-list/icon_dryer_use.png';
				device.typeDesc = '烘干机';
				break;
			case 'blow':
				device.icon = '/assets/equipment-list/icon_hair_dryer.png';
				device.iconUsing = '/assets/equipment-list/icon_hair_dryer_use.png';
				device.typeDesc = '吹风机';
				break;
			case 'access_control':
				device.icon = '/assets/equipment-list/icon_access.png';
				device.iconUsing = '/assets/equipment-list/icon_access_use.png';
				device.typeDesc = '门禁';
				break;
			default:
				device.icon = '/assets/equipment-list/icon_default.png';
				device.iconUsing = '/assets/equipment-list/icon_default_use.png';
				device.typeDesc = '设备';
		}

		return device;
	}

	/**
	 * 控制设备开关
	 * @param {string} deviceId 设备ID
	 * @param {string} action 操作类型 (on/off)
	 * @param {number} duration 使用时长(分钟)
	 * @param {Object} options 额外选项 {storeId, topic}
	 * @returns {Object} 控制结果
	 */
	async controlDevice(deviceId, action, duration = 0, options = {}) {
		// 如果传入了topic参数，直接使用（门禁二维码场景）
		if (options.topic) {
			console.log('使用传入的topic进行设备控制', {
				deviceId,
				action,
				topic: options.topic,
				storeId: options.storeId
			});
			
			let controlResult = await this.sendMqttCommand(options.topic, action, duration);
			
			return {
				success: true,
				message: action === 'on' ? '设备启动成功' : '设备关闭成功',
				data: {
					deviceId,
					action,
					topic: options.topic,
					storeId: options.storeId,
					mqttResult: controlResult
				}
			};
		}
		
		// 原有逻辑：通过deviceId查找设备
		let device = deviceCache.get(deviceId);
		if (!device) {
			if (config.TEST_MODE && !config.TEST_CONFIG.ENABLE_REAL_DEVICE_LIST) {
				device = {
					_id: deviceId,
					name: '测试设备',
					storeId: 'test_store',
					publishTopic: '/test/device/control',
					subscribeTopics: ['/test/device/control'],
					deviceMAC: '00:11:22:33:44:55',
					iotId: 'iot-test',
					appId: 'app-test',
					deviceKey: 'key-test'
				};
				console.log('TEST_MODE: 使用模拟设备数据', { deviceId, mock: { publishTopic: device.publishTopic, subscribeTopics: device.subscribeTopics, deviceMAC: device.deviceMAC } });
			} else {
				// 生产/测试真实模式下从数据库读取
				device = await DeviceModel.getOne({ _id: deviceId }, '*', {}, false);
				if (!device) device = await DeviceModel.getOne(deviceId);
			}
		}
		if (!device) {
			throw new AppError('设备不存在', appCode.DATA_NOT_EXIST);
		}
		// 写入缓存，供后续使用
		deviceCache.set(deviceId, device);

		// 始终使用静态 MQTT 连接配置，不覆盖为设备凭据
		const mqttCfg = device.mqttConfig || {};
		const maskedStaticCfg = {
			protocol: DeviceService._mqttStaticConfig?.protocol,
			host: DeviceService._mqttStaticConfig?.host,
			port: DeviceService._mqttStaticConfig?.port,
			username: DeviceService._mqttStaticConfig?.username ? `${String(DeviceService._mqttStaticConfig?.username).slice(0,2)}***` : undefined,
			clientId: DeviceService._mqttStaticConfig?.clientId ? `${String(DeviceService._mqttStaticConfig?.clientId).slice(0,3)}***` : undefined
		};
		console.log('保持使用静态MQTT连接配置(已脱敏)', maskedStaticCfg);

		// 解析发布主题
		let topic;
		let topicSource = '';
		if (Array.isArray(mqttCfg.subscribeTopics) && mqttCfg.subscribeTopics.length > 0) {
			topic = mqttCfg.subscribeTopics[0];
			topicSource = 'mqttConfig.subscribeTopics[0]';
		} else if (typeof mqttCfg.subscribeTopics === 'string' && mqttCfg.subscribeTopics) {
			topic = mqttCfg.subscribeTopics;
			topicSource = 'mqttConfig.subscribeTopics(string)';
		} else if (device.publishTopic) {
			topic = device.publishTopic;
			topicSource = 'device.publishTopic';
		} else if (Array.isArray(device.subscribeTopics) && device.subscribeTopics.length > 0) {
			topic = device.subscribeTopics[0];
			topicSource = 'device.subscribeTopics[0]';
		} else if (typeof device.subscribeTopics === 'string' && device.subscribeTopics) {
			topic = device.subscribeTopics;
			topicSource = 'device.subscribeTopics(string)';
		} else {
			throw new AppError('设备MQTT发布/订阅主题缺失：请在设备文档mqttConfig.subscribeTopics或publishTopic/subscribeTopics配置主题', appCode.DATA_NOT_EXIST);
		}
		if (typeof topic === 'string' && topic && !topic.startsWith('/')) topic = '/' + topic;
		console.log('控制设备发布主题解析', {
			deviceId,
			usedTopic: topic,
			from: topicSource,
			deviceMAC: device.deviceMAC,
			iotId: device.iotId,
			appId: device.appId,
			deviceKey: device.deviceKey
		});

		let controlResult = await this.sendMqttCommand(topic, action, duration);

		// 更新设备状态（真实写入数据库）
		let updateData = {
			switchStatus: action === 'on',
			status: action === 'on' ? DeviceModel.STATUS.IN_USE : DeviceModel.STATUS.AVAILABLE
		};
		if (action === 'off') {
			updateData.remainingTime = 0; // 秒
			updateData.endTime = timeUtil.time(); // 毫秒
		} else if (action === 'on' && duration > 0) {
			updateData.remainingTime = duration * 60; // 秒
			updateData.endTime = timeUtil.time() + duration * 60 * 1000; // 毫秒
		}
		if (config.TEST_MODE && !config.TEST_CONFIG.ENABLE_REAL_DEVICE_STATUS) {
			console.log('TEST_MODE: 跳过设备状态数据库写入', { deviceId, updateData });
		} else {
			// 并发保护：记录写入时间，并仅在数据库中 lastUpdateTime <= 当前写入时间时更新
			updateData.lastUpdateTime = timeUtil.time();
			const where = { _id: deviceId, lastUpdateTime: ['<=', updateData.lastUpdateTime] };
			await DeviceModel.edit(where, updateData, false);
			console.log('设备状态已写入数据库', { deviceId, updateData, where });
		}

		if (action === 'off') {
			const deviceStatusManager = require('./device_status_manager.js');
			await deviceStatusManager.endDeviceUsage(deviceId, { skipControl: true });
		}

		return {
			success: true,
			message: action === 'on' ? '设备启动成功' : '设备关闭成功',
			deviceId: deviceId,
			action: action,
			duration: duration,
			mqttResult: controlResult
		};
	}

	/**
	 * 发送MQTT控制指令
	 * @param {string} topic MQTT发布主题（使用设备数据 subscribeTopics[0]）
	 * @param {string} action 操作类型
	 * @param {number} duration 时长
	 * @returns {Object} 发送结果
	 */
	async sendMqttCommand(topic, action, duration = 0) {
		console.log(`发送MQTT指令: 主题${topic}, 操作${action}, 时长${duration}分钟`);
		try {
			let message = { type: 'event', key: action === 'on' ? 1 : 0 };
			// 发送前校验凭据完整性，避免无效连接尝试
			if (!this.mqttConfig || !this.mqttConfig.host || !this.mqttConfig.port || !this.mqttConfig.clientId) {
				console.error('MQTT凭据不完整，取消发送', {
					host: this.mqttConfig && this.mqttConfig.host,
					port: this.mqttConfig && this.mqttConfig.port,
					username: this.mqttConfig && this.mqttConfig.username,
					clientId: this.mqttConfig && this.mqttConfig.clientId
				});
				return { success: false, message: 'MQTT凭据不完整，发送取消', topic, payload: message, error: 'MQTT凭据不完整' };
			}
			if (!this.mqttClient || !this.mqttClient.connected) {
				await this.initMqttConnection();
				// 等待连接完成（最多8秒），避免立即判定未连接
				if (this.mqttClient && !this.mqttClient.connected) {
					await new Promise((resolve) => {
						const client = this.mqttClient;
						if (!client) return resolve();
						const timeout = setTimeout(() => {
							client && client.off && client.off('connect', onConnect);
							resolve();
						}, 8000);
						const onConnect = () => {
							clearTimeout(timeout);
							client && client.off && client.off('connect', onConnect);
							resolve();
						};
						client.on('connect', onConnect);
					});
				}
			}
			if (this.mqttClient && this.mqttClient.connected) {
				this.mqttClient.publish(topic, JSON.stringify(message));
				console.log(`MQTT指令发送成功: 主题=${topic}, 消息=${JSON.stringify(message)}`);
				return { success: true, message: 'MQTT指令发送成功', topic, payload: message };
			} else {
				console.error('MQTT连接未建立，发送失败: 未连接到MQTT服务器');
				// 触发故障处理
				await this.handleDeviceCommandFailure(topic, 'no_response', 'MQTT连接未建立');
				return { success: false, message: 'MQTT连接未建立，发送失败', topic, payload: message, error: 'MQTT未连接' };
			}
		} catch (error) {
			console.error('MQTT指令发送失败:', error);
			// 触发故障处理
			await this.handleDeviceCommandFailure(topic, 'unknown', error.message);
			return { success: false, message: 'MQTT指令发送失败', error: error.message };
		}
	}

	/**
	 * 处理设备指令失败
	 * @param {string} topic MQTT主题
	 * @param {string} faultType 故障类型
	 * @param {string} faultMessage 故障信息
	 */
	async handleDeviceCommandFailure(topic, faultType, faultMessage) {
		try {
			// 从topic中提取设备ID（如果可能）
			let deviceId = null;
			// 尝试从缓存中找到对应的设备
			for (const [cachedDeviceId, device] of deviceCache.entries()) {
				if (device.publishTopic === topic || 
					(Array.isArray(device.subscribeTopics) && device.subscribeTopics.includes(topic)) ||
					device.subscribeTopics === topic) {
					deviceId = cachedDeviceId;
					break;
				}
			}

			if (deviceId) {
				// 异步触发故障处理，不阻塞主流程
				setImmediate(async () => {
					try {
						const SimpleFaultHandler = require('./simple_fault_handler.js');
						const faultHandler = new SimpleFaultHandler();
						await faultHandler.handleDeviceFault(deviceId, faultType, faultMessage);
					} catch (faultError) {
						console.error('故障处理失败:', faultError);
					}
				});
			} else {
				console.warn('无法从topic确定设备ID，跳过故障处理', { topic, faultType, faultMessage });
			}
		} catch (error) {
			console.error('处理设备指令失败时发生错误:', error);
		}
	}

	/**
	 * 更新设备状态
	 * @param {string} deviceId 设备ID
	 * @param {number} status 设备状态
	 * @returns {Object} 更新结果
	 */
	async updateDeviceStatus(deviceId, status) {
		let updateData = {
			status: status
			// 移除 updateTime 字段，让框架自动处理 EDIT_TIME
		};

		await DeviceModel.edit(deviceId, updateData);

		return {
			success: true,
			message: '设备状态更新成功',
			deviceId: deviceId,
			status: status
		};
	}

	/**
	 * 获取设备实时状态
	 * @param {string} deviceId 设备ID
	 */
	async getDeviceRealTimeStatus(deviceId) {
		const deviceStatusManager = require('./device_status_manager.js');
		let device = deviceCache.get(deviceId);
		if (!device) {
			if (config.TEST_MODE && !config.TEST_CONFIG.ENABLE_REAL_DEVICE_LIST) {
				device = { _id: deviceId, name: '测试设备', storeId: 'test_store' };
				deviceCache.set(deviceId, device);
			} else {
				device = await DeviceModel.getOne({ _id: deviceId }, '*', {}, false);
				if (!device) {
					throw new Error('设备不存在');
				}
			}
		}
		const status = await deviceStatusManager.getDeviceRealTimeStatus(deviceId);
		if (!status) return null;
		return {
			deviceId,
			status: status.status,
			remainingTime: status.remainingTime,
			startTime: status.startTime,
			endTime: status.endTime,
			currentOrderId: status.orderId,
			lastUpdateTime: status.lastUpdateTime
		};
	}

	/**
	 * 批量获取门店设备状态
	 * @param {string} storeId 门店ID
	 */
	async getStoreDevicesRealTimeStatus(storeId) {
		// 使用设备状态管理器批量获取状态
		const deviceStatusManager = require('./device_status_manager.js');
		const list = await deviceStatusManager.getStoreDevicesStatus(storeId);
		// 统一对外：remainingTime 为秒
		return list.map(item => ({
			...item,
			remainingTime: item.remainingTime // 秒，保持不变
		}));
	}

	/**
	 * 批量更新设备状态（用于定时任务）
	 */
	async batchUpdateDeviceStatus() {
		// 查询所有使用中的设备
		const usingDevices = await DeviceModel.getAll({
			status: DeviceModel.STATUS.IN_USE
		});

		let updatedCount = 0;
		const currentTime = timeUtil.time();

		for (let device of usingDevices) {
			if (device.endTime && currentTime >= device.endTime) {
				// 设备使用时间到期，自动关闭
				await this.controlDevice(device._id, 'off');
				updatedCount++;
			}
		}

		return {
			success: true,
			message: `更新了 ${updatedCount} 个设备状态`,
			updatedCount: updatedCount
		};
	}

}

module.exports = DeviceService;